﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit;
using NUnit.Framework;
using System.Xml.Linq;
using XmlMerge.Interfaces;
using DataSetMerge.DataTableOperators;

namespace HarvestMergeTests
{
    [TestFixture]
    class WixXmlOperatorTests
    {
        XElement target;
        XElement source;
        IXmlOperator op;

        [SetUp]
        public void Setup()
        {
            target = new XElement("Wix", new XElement[] {
                new XElement("Fragment", new XElement[] { 
                    new XElement("Component", new object[] { new XAttribute("Id", "Target"), 
                        new XElement("File", new object[] {new XAttribute("Source", "target.exe"),
                            new XElement("Service", new object[] {new XElement("ServiceControl", new XAttribute("Value", "Start"))})
                        })}),
                        new XElement("Component", new object[] {
                            new XAttribute("Id", "Duplicate"),
                            new XElement("File", new object[]{ 
                                new XAttribute("Source", "duplicate.dll")})})
                    }),
                    new XElement("Fragment", new object[] {
                        new XElement("ComponentGroup", new object[] {
                            new XAttribute("Id", "Tergrt"),
                            new XElement("ComponentRef", new XAttribute("Id", "Target")),
                            new XElement("ComponentRef", new XAttribute("Id", "Duplicate"))
                        })
                    })
                });

            source = new XElement("Wix", new XElement[] {
                new XElement("Fragment", new XElement[] { 
                    new XElement("Component", new object[] { new XAttribute("Id", "Addition"), 
                        new XElement("File", new object[] {new XAttribute("Source", "source.exe"),
                            new XElement("Stuff", new object[] {new XElement("Extraneous", new XAttribute("Value", "Test"))})
                        })}),
                        new XElement("Component", new object[] {
                            new XAttribute("Id", "SecDuplicate"),
                            new XElement("File", new object[]{ 
                                new XAttribute("Source", "duplicate.dll")})})
                }),
                new XElement("Fragment", new object[] {
                        new XElement("ComponentGroup", new object[] {
                            new XAttribute("Id", "Serce"),
                            new XElement("ComponentRef", new XAttribute("Id", "Addition")),
                            new XElement("ComponentRef", new XAttribute("Id", "SecDuplicate"))
                        })
                    })
            });

            op = new WixXmlTableOperator();
        }

        [Test]
        public void GivenXMLWithDifferentData_WhenRemoveDuplicateEntries_ThenTargetDataXmlDupliucateDateIsRemoved()
        {
            op.RemoveDuplicateEntries(source, target);

            Assert.IsTrue((from i in source.Descendants("File")
                           where i.Attribute("Source").Value == "duplicate.dll"
                           select i).Count() == 0);
        }

        [Test]
        public void GivenXMLWithChildlessComponenets_WhenRemoveChildlessRows_ThenTargetDataXmlChildlessComponenetsRemoved()
        {
            op.RemoveDuplicateEntries(source, target);

            Assert.IsTrue((from i in source.Descendants("Component")
                           where i.Attribute("Id").Value == "SecDuplicate"
                           select i).Count() == 0);
        }

        [Test]
        public void GivenXmlData_WhenAddEntries_ThenEntriesNotPresentinTargetAreAddedToTarget()
        {
            XElement expected = new XElement("Wix", new XElement[] {
                new XElement("Fragment", new XElement[] { 
                    new XElement("Component", new object[] { new XAttribute("Id", "Target"), 
                        new XElement("File", new object[] {new XAttribute("Source", "target.exe"),
                            new XElement("Service", new object[] {new XElement("ServiceControl", new XAttribute("Value", "Start"))})
                        })}),
                        new XElement("Component", new object[] {
                            new XAttribute("Id", "Duplicate"),
                            new XElement("File", new object[]{ 
                                new XAttribute("Source", "duplicate.dll")})}),
                        new XElement("Component", new object[] { new XAttribute("Id", "Addition"), 
                        new XElement("File", new object[] {new XAttribute("Source", "source.exe"),
                            new XElement("Stuff", new object[] {new XElement("Extraneous", new XAttribute("Value", "Test"))})
                        })})
                    }),
                    new XElement("Fragment", new object[] {
                        new XElement("ComponentGroup", new object[] {
                            new XAttribute("Id", "Tergrt"),
                            new XElement("ComponentRef", new XAttribute("Id", "Target")),
                            new XElement("ComponentRef", new XAttribute("Id", "Duplicate")),
                             new XElement("ComponentRef", new XAttribute("Id", "Addition"))
                        })
                    })
                });

            op.RemoveDuplicateEntries(source, target);
            op.AddNewEntries(target, source);

            Assert.AreEqual(expected.ToString(), target.ToString());
        }

        [Test]
        public void GivenXmlData_WhenRemoveSuntractedEntries_ThenEntriesNotPresentInSourceAreremovedFromTarget()
        {
            op.RemoveDuplicateEntries(source, target);
            op.RemoveSubtractedEntries(target, source);

            Assert.IsTrue(target.Descendants("Componenet").Count() == 0);
        }
    }
}
